package com.zmh.service.httpclient;

import java.awt.print.Book;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.xml.ws.Response;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.InitBinder;

import com.alibaba.fastjson.JSON;
import com.zmh.common.DateUtil;
import com.zmh.dao.BookDao;
import com.zmh.model.book.BookInfo;

/**
 * @author zhoumh
 * @version 创建时间：2017年7月19日 下午4:31:12
 * @Description  还是要做修改，多次调用，获取所有链接，做302跳转之后的地址
 */
@Service
@SuppressWarnings("deprecation")
public class BookLink20171012 {
	private static Logger logger = LoggerFactory.getLogger(BookLink20171012.class);
	@Autowired
	private BookDao bookDao;
	static BookLink20171012 bookLink;
	static CloseableHttpClient httpClient = null;
	static RequestConfig requestConfig = null;
	static Map<String,String> cookieMap = new HashMap<String, String>(64);
	@PostConstruct
	public void init(){
		bookLink = this;
		bookLink.bookDao = this.bookDao;
	}
	/**
	 * 获取booklink的书架信息，与数据库进行比对找出有更新的书籍
	 * @author zhoumh
	 * @version 创建时间：2017年10月8日 下午4:35:03
	 */
	public void getBookLink() {
		//获取booklink书架信息
		
		//与数据库记录的最新信息进行比对
		//如果有更新就进行提醒并更新数据库
	}
	
	/**
	 * 简单的获取一个HTML页面的内容
	 */
	public static void getHTML() {
		// 设置上下文环境
		HttpClientContext httpContext = HttpClientContext.create();
		// 设置cookie
		requestConfig = RequestConfig.custom()
				.setConnectionRequestTimeout(10000)
				.setConnectTimeout(10000)
				.setCookieSpec(CookieSpecs.STANDARD_STRICT)
				.build();
		try {
			// 生成一个httpclient对象
			httpClient = HttpClients.custom()
					.setSSLSocketFactory(createSSLConnSocketFactory()) //创建SSL，没有效果
					.setDefaultRequestConfig(requestConfig)
					.build();
			CloseableHttpResponse response = null; //注意不要使用HttpResponse对象
			// 设置POST参数
			List<NameValuePair> formparams = new ArrayList<NameValuePair>();
			formparams.add(new BasicNameValuePair("username", "wwwxeb"));
			formparams.add(new BasicNameValuePair("passwd", "8303523"));
			formparams.add(new BasicNameValuePair("cookie", "4"));
			UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
			// 发起登陆请求
			response = doPost(httpClient, "https://2.booklink.me/after_login.php", uefEntity);
//			System.out.println(" \n >>>>>>>>>>>>>>>>>>>>>>>>>>>发起登陆请求返回结果：");
//			respHandler(response,httpContext);
			// 获取书架上的所有书籍名称和最新更新
			String url = "https://2.booklink.me/fav_book.php";
//			String url = "https://2.booklink.me/fav_book.php?shelf_id=1";
			response = doGet(httpClient, httpContext, url);
//			System.out.println(" \n >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>打开书架请求返回结果： ");
			String content = respHandler(response,httpContext);
			bookHandler(content,httpContext);
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 关闭或释放资源
			try {
				httpClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	/**
	 * 返回结果处理
	 * @return String
	 * @author zhoumh
	 * @version 创建时间：2017年7月27日 下午3:14:29
	 */
	public static String respHandler(CloseableHttpResponse response, HttpClientContext httpContext) throws ParseException, IOException {
		String content = "";
//		System.out.println("StatusLine ：" + response.getStatusLine().getStatusCode());
//		System.out.println("Location[]: " + response.getFirstHeader("location").getValue());
//		System.out.println("HEADER[]: " + JSON.toJSONString(response.getAllHeaders()));
//		String bookUri = httpContext.getRedirectLocations().get(0).toString();
//		String[] bookPath = httpContext.getRedirectLocations().get(0).getPath().split("/");
		// 返回状态信息
		StatusLine statusLine = response.getStatusLine();
		// 返回http代码:200/400/500 HttpStatus.OK.toString();
//		int statusCode = statusLine.getStatusCode();
		// 返回http响应：OK
//		String reasonPhrase = statusLine.getReasonPhrase();
		// 返回http版本:HTTP/1.1
		// ProtocolVersion protocolVersion = statusLine.getProtocolVersion();
		// 获取返回消息实体
		HttpEntity entity = response.getEntity();
		// 返回的所有header
		Header[] header = response.getAllHeaders();
		// 判断返回实体是否为空
		if (entity != null) {
			// 获取返回的内容编码
			Header contentEncoding = entity.getContentEncoding();
			// 获取返回的内容
			content = EntityUtils.toString(entity, "UTF-8");
			System.out.println("response content（返回的内容）: \n " + content);
		}
		return content;

	}
	/**
	 * 书架信息处理
	 * @author zhoumh
	 * @version 创建时间：2017年8月29日 下午5:26:07
	 * @throws IOException 
	 * @throws ClientProtocolException 
	 */
	public static void bookHandler(String content,HttpClientContext httpContext) throws ClientProtocolException, IOException{
		//对返回的书架内容做解析，将每本书的名称地址信息提取出来
		Document doc = Jsoup.parse(content);
		//选择书籍所在行
		Elements links = doc.select("tr[bgcolor=#fffff0],tr[bgcolor=#f0f0f0]");
		List<BookInfo> books = new ArrayList<>();
		for (Element element : links) {
			BookInfo book = new BookInfo();
			String name = "";
			String href = element.select("a[href^=/jump_c.php]").attr("href");
			//如果没有书籍链接，就跳过
			if (href.length()<1) {
				continue;
			}
			Elements es = element.select("a[href^=/book]"); //书名和最新章节属性相似，再做个循环区分
			for (Element element2 : es) {
				String title = element2.select("a[title*=更新时间]").attr("title");
				//如果元素是更新时间，就跳过
				if (title.length()>0) {
					continue;
				}
				name = element2.text();
			}
			
			//设置书名
			book.setName(name);
			//书籍链接
			httpClient = HttpClients.custom()
					.setSSLSocketFactory(createSSLConnSocketFactory()) //创建SSL，没有效果
					.setDefaultRequestConfig(requestConfig)
					.build();
			String temp = respHandler(doGet(httpClient, httpContext, "https://booklink.me"+href),httpContext);
			httpClient.close();
			URI uri = httpContext.getRedirectLocations().get(0);
			String host = uri.getHost();
			String bookUrl = uri.toString();
			String[] bookPath = uri.getPath().split("/");
			if ("vipreader.qidian.com".equals(host)) {
				bookUrl = "https://book.qidian.com/info/"+bookPath[2];
			}
			if ("book.zongheng.com".equals(host)) {
				bookUrl = "http://book.zongheng.com/book/"+bookPath[2];
			}
			if ("www.motie.com".equals(host)) {
				bookUrl = bookUrl.substring(0, bookUrl.lastIndexOf("_"));
			}
			if ("yc.ireader.com.cn".equals(host)) {
				
			}
			if ("chuangshi.qq.com".equals(host)) {
				
			}
			if ("www.tadu.com".equals(host)) {
				
			}
			book.setUrl(bookUrl);
			System.out.println(name+" : "+host+" : "+bookUrl);
//			bookLink.bookDao.insertBook(book);
			
		}
//		System.out.println("\n " + form);
	}
	
	
	/**
	 * 根据传入的URL和httpclient发起get请求并返回结果
	 * 
	 * @author zhoumh
	 * @version 创建时间：2017年7月26日 下午5:18:47
	 */
	public static CloseableHttpResponse doGet(CloseableHttpClient httpClient, HttpClientContext httpContext, String url)
			throws ClientProtocolException, IOException {
		HttpGet httpGet = new HttpGet(url);
		// 配置请求的HEADER部分
		httpGet.addHeader(HttpHeaders.ACCEPT, "application/xml");
		// 接收返回信息
		CloseableHttpResponse response = httpClient.execute(httpGet, httpContext);
		return response;
	}
	/**
	 * 根据传入的URL和httpclient发起POST请求并返回结果
	 * @author zhoumh
	 * @version 创建时间：2017年7月26日 下午5:19:23
	 * @throws IOException
	 * @throws ClientProtocolException
	 */
	public static CloseableHttpResponse doPost(CloseableHttpClient httpClient,
			String url, UrlEncodedFormEntity uefEntity)
			throws ClientProtocolException, IOException {
		// Post请求
		HttpPost httppost = new HttpPost(url);
		httppost.setEntity(uefEntity);
		// 发送请求并接收返回信息
		CloseableHttpResponse response = httpClient.execute(httppost);
		return response;
	}
	
	
    /**
     * 从响应信息中获取cookie
     * @author zhoumh
     * @version 创建时间：2017年7月27日 下午3:43:05
     */
    public static String setCookie(CloseableHttpResponse httpResponse)
    {
        System.out.println("----setCookieStore");
        Header headers[] = httpResponse.getHeaders("Set-Cookie");
        if (headers == null || headers.length==0)
        {
            System.out.println("----there are no cookies");
            return null;
        }
        String cookie = "";
        for (int i = 0; i < headers.length; i++) {
            cookie += headers[i].getValue();
            if(i != headers.length-1)
            {
                cookie += ";";
            }
        }
 
        String cookies[] = cookie.split(";");
        for (String c : cookies)
        {
            c = c.trim();
            if(cookieMap.containsKey(c.split("=")[0]))
            {
                cookieMap.remove(c.split("=")[0]);
            }
            cookieMap.put(c.split("=")[0], c.split("=").length == 1 ? "":(c.split("=").length ==2?c.split("=")[1]:c.split("=",2)[1]));
        }
        System.out.println("----setCookieStore success");
        String cookiesTmp = "";
        for (String key :cookieMap.keySet())
        {
            cookiesTmp +=key+"="+cookieMap.get(key)+";";
        }
 
        return cookiesTmp.substring(0,cookiesTmp.length()-2);
    }
    
    /**
     * 创建SSL安全连接 
     * @author zhoumh
     * @version 创建时间：2017年7月27日 下午3:19:10
     */
    @SuppressWarnings({"unused"})
	private static SSLConnectionSocketFactory createSSLConnSocketFactory() {  
        SSLConnectionSocketFactory sslsf = null;  
        try {  
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {  
            	@Override
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
                    return true;  
                }  
            }).build();  
            sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {  
  
                @Override  
                public boolean verify(String arg0, SSLSession arg1) {  
                    return true;  
                }  
  
                @Override  
                public void verify(String host, SSLSocket ssl) throws IOException {  
                }  
  
                @Override  
                public void verify(String host, X509Certificate cert) throws SSLException {  
                }  
  
                @Override  
                public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {  
                }  
            });  
        } catch (GeneralSecurityException e) {  
            e.printStackTrace();  
        }  
        return sslsf;  
    }  

	/**
	 * 下载一个文件到本地
	 */
	public static void downloadFile() {
		CloseableHttpClient httpClient = null;
		InputStream iStream = null;
		FileOutputStream foStream = null;
		// 设置cookie
		RequestConfig requestConfig = RequestConfig.custom()
				.setCookieSpec(CookieSpecs.STANDARD_STRICT).build();

		try {
			httpClient = HttpClients.createDefault(); // 生成一个httpclient对象
			httpClient = HttpClients.custom()
					.setDefaultRequestConfig(requestConfig).build();
			HttpGet httpGet = new HttpGet(
					"http://ww2.sinaimg.cn/large/9d57a855jw1dqpv9fp4yuj.jpg"); // 传入一张图片的地址

			System.out.println("文件正在下载...");
			CloseableHttpResponse response = httpClient.execute(httpGet);
			HttpEntity entity = response.getEntity();

			iStream = entity.getContent();
			File file = new File("d:/cat.jpg"); // 图片对象
			foStream = new FileOutputStream(file);
			int i = -1;
			byte[] tmp = new byte[1024];
			while ((i = iStream.read(tmp)) != -1) {
				foStream.write(tmp, 0, i);
			}
			System.out.println("文件下载完毕...");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				foStream.flush();
				foStream.close();
				iStream.close();
				httpClient.close();
				System.out.println("数据流已关闭....");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}


}
